<?php
namespace app\integration;

use app\exception\CommonException;
use app\plugins\httpclient\HttpClient;
use think\facade\Cache;

class HuobiApi
{
    // 常量定义规范化
    public const SERVICE = 'huobi';
    public const HISTORY_URL = '/market/history/kline?period=[period]&size=300&symbol=[symbol]usdt';
    public const CACHE_PREFIX = 'market.';
    public const KLINE_SUFFIX = '.kline.';

    /**
     * 获取K线历史数据
     *
     * @param string $interval 时间间隔（如1min, 1hour, 1day）
     * @param string $symbol 交易对符号（如btc, eth）
     * @return array 历史K线数据
     * @throws CommonException 当API请求失败时抛出
     */
    public function getHistory(string $interval, string $symbol): array
    {
        // 验证输入参数
        if (empty($interval) || empty($symbol)) {
            throw new CommonException('参数不能为空');
        }

        // 解析时间间隔
        $timeParts = $this->parseInterval($interval);
        $cacheTtl = $this->calculateCacheTtl($timeParts['unit'], $timeParts['value']);
        $formattedInterval = "{$timeParts['value']}{$timeParts['unit']}";

        // 生成缓存键
        $cacheKey = self::CACHE_PREFIX . "{$symbol}usdt" . self::KLINE_SUFFIX . $formattedInterval;

        // 尝试从缓存获取
        $cachedData = Cache::store('redis')->get($cacheKey);
        if (!empty($cachedData)) {
            return $cachedData;
        }

        // 缓存未命中，请求API
        try {
            $httpClient = HttpClient::getInstance();
            $httpClient->init(self::SERVICE);

            $url = str_replace(
                ['[period]', '[symbol]'],
                [$formattedInterval, $symbol],
                self::HISTORY_URL
            );

            $response = $httpClient->request($url, 'get');

            // 验证API响应
            if (!isset($response['status']) || $response['status'] !== 'ok') {
                throw new CommonException(
                    '获取K线数据失败: ' . ($response['err-msg'] ?? '未知错误')
                );
            }

            $data = array_values($response["data"]);
            // 缓存数据
            Cache::store('redis')->set($cacheKey, $data, $cacheTtl);

            return $response["data"];
        } catch (\Exception $e) {
            throw new CommonException('获取K线数据异常: ' . $e->getMessage());
        }
    }

    /**
     * 获取实时行情数据
     *
     * @param string $symbol 交易对符号
     * @return array 实时行情数据（包含涨跌幅）
     * @throws CommonException 当缓存数据不存在时抛出
     */
    public function polling(string $symbol): array
    {
        if (empty($symbol)) {
            throw new CommonException('交易对符号不能为空');
        }

        $nowKey = self::CACHE_PREFIX . "{$symbol}usdt" . self::KLINE_SUFFIX . '1sec';
        $yesterdayKey = self::CACHE_PREFIX . "{$symbol}usdt" . self::KLINE_SUFFIX . 'yesterday';
        $detailKey = self::CACHE_PREFIX . "{$symbol}usdt" . self::KLINE_SUFFIX . 'detail';

        // 获取缓存数据
        $nowData = Cache::store('redis')->get($nowKey);
        $yesterdayData = Cache::store('redis')->get($yesterdayKey);
        $detailData     = Cache::store('redis')->get( $detailKey);
        // 验证缓存数据
        if (empty($nowData) || empty($yesterdayData)||empty($detailData)) {
            throw new CommonException('实时行情缓存数据不存在');
        }

        // 计算涨跌幅（增加除以零保护）
        $change = 0;
        if (isset($nowData['close'], $yesterdayData['close']) && $yesterdayData['close'] != 0) {
            $change = 100 * ($nowData['close'] - $yesterdayData['close']) / $yesterdayData['close'];
            $change = round($change, 4); // 保留两位小数
        }

        $nowData['change'] = $change;
        $nowData["high_24"] =  number_format($detailData["high"], 2);
        $nowData["close_24"] =  number_format($detailData["close"], 2);
        $nowData["amount_24"] = number_format($detailData["amount"], 2);
        $nowData["vol_24"] =  intval($detailData["vol"]);
        return $nowData;
    }

    /**
     * 解析时间间隔字符串
     *
     * @param string $interval 时间间隔（如1min, 1hour, 1day）
     * @return array 包含单位和数值的数组
     * @throws CommonException 当格式无效时抛出
     */
    private function parseInterval(string $interval): array
    {
        if (!preg_match('/^(\d+)(min|hour|day|week|mon|year)$/i', $interval, $matches)) {
            throw new CommonException("无效的时间间隔格式: {$interval}");
        }

        return [
            'value' => intval($matches[1]),
            'unit' => strtolower($matches[2])
        ];
    }

    /**
     * 计算缓存过期时间
     *
     * @param string $unit 时间单位
     * @param int $value 时间值
     * @return int 缓存过期时间（秒）
     */
    private function calculateCacheTtl(string $unit, int $value): int
    {
        $secondsPerUnit = [
            'min' => 60,
            'hour' => 3600,
            'day' => 86400,
            'week' => 604800,
            'mon' => 2592000, // 30天近似值
            'year' => 31536000 // 365天近似值
        ];

        return $value * ($secondsPerUnit[$unit] ?? 3600); // 默认1小时
    }
}